package models;
import java.util.ArrayList;
import java.util.List;

public class Hand {

	int handSize = 5;
	Card[] cards;
	List<Card> inHand = new ArrayList<Card>();
	
	/**
	 * Gives hand the card
	 * @param card a card which should be given the hand
	 */
	public final void giveCard(final Card card) {
		if(inHand.size() < handSize) inHand.add(card);
	}

	/**
	 * Get the actual value of cards included in the hand
	 * @return list of integers, bigger numbers - better set of cards
	 * 
	 * Values:
	 * Straight Flush	9, Highest card
	 * Four Of A Kind	7, Figure of four 
	 * Full				6, Figure of three, Figure of pair
	 * Flush			5, Figures from the highest to the lowest
	 * Straight			4, Highest card
	 * Three Of A Kind	3, Figure of three
	 * Two Pair			2, Higher figure of pair, Lower figure of pair
	 * One Pair			1, Figure of pair
	 * High Card		0, Figures from the highest to the lowest
	 */
	public final List<Integer> getValue() {
		if(inHand.size() < handSize) return null;
		
		cards = new Card[handSize + 1];
		int[] viTable = new int[handSize]; 
		List<Integer> finalValue = new ArrayList <Integer>();
		sort();
		
		int value = 0;
		boolean color = false, order = false;
		
		for (int i = 0; i < handSize - 1; i++) {
			if(cards[i].getColor() != cards[i+1].getColor()) {
				color = false;
				break;
			} else {
				if ( i == handSize - 2){
					color = true;
					value += 5;
				}
			}
		}
		for (int i = 0; i < handSize - 1; i++) {
			if(cards[i].getFigure() != cards[i+1].getFigure()-1) {
				order = false;
				break;
			} else {
				if (i == handSize - 2) {
					order = true;
					value += 4;
				}
				
			}
		}
		
		int j = 1;
		if (!color && !order) {
			for(int i = 0; j <= handSize; j++){
				
				if(j == handSize || cards[i].getFigure() != cards[j].getFigure()){
					if (i+2 == j) {
						value += 1;
						viTable[i] = viTable[i+1] = 2;  
					}
					if (i+3 == j) {
						value += 3;
						viTable[i] = viTable[i+1] = viTable[i+2] = 3;
					}
					if (i+4 == j) {
						value += 5;
						viTable[i] = viTable[i+1] = viTable[i+2] = viTable[i+3] = 4;
					}
					i = j;
				}
			}
			if (value > 3) value += 2;
		}
		finalValue.add(value);
		if(value == 9 || value == 4) {
			finalValue.add(cards[handSize-1].getFigure());
		}
		
		else if (value == 5 || value == 0) {
			for (int i = 1; i < handSize + 1; i++) {
				finalValue.add(cards[handSize - i].getFigure());
			}
		}
		
		else {
			for (int i = handSize - 1; i >= 0; i--){
				if (viTable[i] == 4) {
					finalValue.add(cards[i].getFigure());
					break;
				}
			}
			
			for (int i = handSize - 1; i >= 0; i--){
				if (viTable[i] == 3) {
					finalValue.add(cards[i].getFigure());
					i -= 2;
				}
			}
			
			for (int i = handSize - 1; i >= 0; i--){
				if (viTable[i] == 2) {
					finalValue.add(cards[i].getFigure());
					i--;
				}
			}
		}
		
		for(int i = 0; i < viTable.length; i++)
		{
			System.out.print(viTable[i]);
		}
		
		return finalValue;
	}
	
	final void sort() {
		// Bubble sort
		for (int i = 0; i < handSize; i++) {
			cards[i] = inHand.get(i);
		}
		for(int j = handSize; j >= 0; j--)
		{
			for (int i = 0; i < j - 1; i++) {
				if (cards[i].getFigure() > cards[ i + 1 ].getFigure()) {
					cards[handSize] = cards[i];
					cards[i] = cards[ i + 1 ];
					cards[i+1] = cards[handSize];
					cards[handSize] = null;
				}
			}
		}
	}

	/**
	 * Returns copy of included cards
	 * @return unsorted copy of cards included in collection
	 */
	public final List<Card> showCards() {
		return inHand;
	}

	/**
	 * Removes card from the hand
	 * @param card card to remove
	 * @return removed card
	 */
	public final void takeCard(final Card card) {
		if(!inHand.contains(card)) {
			throw new HandException ("There is not card: " + card.toString());
		}
		inHand.remove(card);
		//return card;
	}
	
	public final void takeCard() {
		inHand.clear();
	}

	/**
	 * Returns number of cards needed for hand to play
	 * @return number of cards needed for hand to play
	 */
	public final int getNumberOfNeededCards() {
		return handSize;
	}

	/**
	 * Returns max number of cards to exchange
	 * @return max number of cards to exchange
	 */
	public final int getMaxNumberOfCardsToExchange() {
		return 4;
	}

	/**
	 * Returns min number of cards to exchange
	 * @return min number of cards to exchange
	 */
	public final int getMinNumberOfCardsToExchange() {
		return 0;
	}

}
